package oop.ex2.expression;

import java.util.ArrayList;

import oop.ex2.exceptions.EmptyExpression;
import oop.ex2.exceptions.ExpectedAtomicExpression;
import oop.ex2.exceptions.ExpectedBinaryOperation;
import oop.ex2.exceptions.TerminatingStringNotFound;
import oop.ex2.exceptions.TokenNotRecognized;
import oop.ex2.exceptions.UnrecognizedVariable;
import oop.ex2.tokenizer.Tokenizer;

/**
 * This represents a node in the expression tree.
 * It has two main functions:
 * 1) While building the tree, it receives a TokenAnalyzer as input and builds it's children.
 * 2) While calculating the tree, it uses it's children to return an output value.
 * 
 * Note that the expression nodes are only concerned with calculating the value of an expression.
 * They don't do any of the string parsing which is used to build the tree. For that they use a
 * tokenizer instance.
 * @author daniel_i_l
 *
 */
public abstract class ExpressionNode {
	protected ArrayList<ExpressionNode> _children;
	protected NodeType _nodeType; //This is set in the subclass's constructor.
	protected String _matchedString;
	
	/**
	 * Construct an Expression node and store the matched 
	 * string that caused this node to be created.
	 * @param matchedString The string that was matched.
	 */
	public ExpressionNode(String matchedString) {
		_children = new ArrayList<ExpressionNode>();
		_matchedString = matchedString;
	}
	
	
	/**
	 * Use a token analyzer in order to build the child nodes. It uses the token analyzer to
	 * advance one by one through the tokens and use them to construct the children based on the
	 * node's internal structure.
	 * @param tokenAnalyzer The token analyzer to use.
	 * @throws EmptyExpression an empty expression was encountered.
	 * @throws ExpectedAtomicExpression if an atomic symbol was expected and not found.
	 * @throws ExpectedBinaryOperation  if a binary operation was expected and not found.
	 * @throws TerminatingStringNotFound  if the end of an sequence was expected and not found.
	 */
	public abstract void generateChildren(Tokenizer tokenizer)  throws TokenNotRecognized, EmptyExpression, ExpectedAtomicExpression, ExpectedBinaryOperation, TerminatingStringNotFound;
	
	
	/**
	 * Calculate the value of this node based on its children. It recursively uses the values
	 * of it;s children in order to calculate it's own value. 
	 * @return The value of this node.
	 * @throws UnrecognizedVariable If non existing variable was encountered 
	 * during the evaluation.
	 */
	public abstract double calculateNode() throws UnrecognizedVariable;
	
	/**
	 * Return the type of the node.
	 * @return The node type.
	 */
	public NodeType getType()
	{
		return _nodeType;
	}
	
	/**
	 * Add a node to the list of children.
	 * @param node The node to add.
	 */
	public void addChild(ExpressionNode node)
	{
		_children.add(node);
	}
	/**
	 * Returns the part of the expression that was matched in order to generate this node.
	 * @return The matched string.
	 */
	public String getMatchedString()
	{
		return _matchedString;
	}
}
